package com.zygh.lz.security;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zygh.lz.dao.SignboardMapper;
import com.zygh.lz.entity.signfile.SignBoard;
import com.zygh.lz.stapprove.SysLogAspect;
import com.zygh.lz.util.JwtTokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * OncePerRequestFilter
 * 过滤器
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private SignboardMapper signboardMapper;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;


    private String tokenHeader = "token";
    private String tokenHead = "Bearer";

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        String authHeader = request.getHeader(this.tokenHeader);

        //判断是PC还是APP

        String ua = request.getHeader("User-Agent");

        //APP请求过滤掉
        if (authHeader != null && authHeader.startsWith(this.tokenHead) && !SysLogAspect.checkAgentIsMobile(ua)) {
            String authToken = authHeader.substring(this.tokenHead.length());

            String username = jwtTokenUtil.getUserNameFromToken(authToken);
            if (username != null) {
                String remoteIP = SysLogAspect.getRemoteIP(request);
                SignBoard signBoard = signboardMapper.selectOne(Wrappers.<SignBoard>lambdaQuery()
                        .eq(SignBoard::getName, username).orderByDesc(SignBoard::getCreateTime)
                        .last("limit 1"));
                /*if (signBoard != null && !remoteIP.equals(signBoard.getIp())) {

                    response.setContentType("application/json;charset=UTF-8");
                    ServletOutputStream outputStream = response.getOutputStream();
                    Map<String, Object> map = new HashMap<>();
                    map.put("code", 403);
                    map.put("msg", "您被迫下线了");
                    map.put("data", null);
                    outputStream.write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
                    outputStream.flush();
                    outputStream.close();
                }*/


                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    //LOGGER.info("authenticated user:{}", username);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                } else {
                    throw new ServletException("Invalid token");
                }
            }
        }
        chain.doFilter(request, response);
    }
}
